<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <ul id="fragment">
      <li>1</li>
      <li>2</li>
      <li>3</li>
    </ul>
  </div>
  <script>
    // 1. [].slice.call(lis)：将伪数组转换为真数组
    const lis = document.getElementsByTagName('li');
    console.log(lis instanceof Array) // false lis是一个伪数组
    // 但是可以像数组一样使用
    // slice方法返回一个从开始到结束选择的数组的一部分浅拷贝到一个新的数组
    // call指定lis对象调用，call让一个函数成为指定对象的方法进行调用
    const lisArr = Array.prototype.slice.call(lis)
    console.log(lisArr instanceof Array)


    // 2. node.nodeType：得到节点类型
    // 最大的node是document[html]、element、attr、text
    const elementNode = document.getElementById('app')
    const attrNode = elementNode.getAttributeNode('id')
    const textNode = elementNode.firstChild
    console.log(elementNode.nodeType, attrNode.nodeType, textNode.nodeType) // 1 2 3

    // 3. Object.defineProperty(obj, propertyName, {})：给对象添加属性，指定描述符
    const obj = {
      firstName: 'zhang',
      lastName: 'san'
    }
    // 给obj添加fullname属性，而且可以自动同步
    // configurable是否可以重新定义
    // value初始值
    // writable是否可以修改
    // enumerable是否可以枚举
    // get回调函数 动态计算得到当前属性值
    // set回调函数 监视当前属性值的变化
    Object.defineProperty(obj, 'fullName', {
      get () {
        return this.firstName + ' ' + this.lastName
      },
      set (value) {
        const name = value.split(' ')
        this.firstName = name[0]
        this.lastName = name[1]
      }
    })
    console.log(obj.fullName)
    obj.firstName = 'LI'
    obj.lastName = 'SI'
    console.log(obj.fullName)
    obj.fullName = 'Wang Wu'
    console.log(obj.firstName, obj.lastName)
    // 4. Object.keys(obj)：得到对象自身可枚举属性组成的数组
    // 5. obj.hasOwnProperty(prop)：判断prop是否是obj自身的属性
    // 6. DocumentFragment：文档碎片，高效批量更新多个节点
    const ul = document.getElementById('fragment')
    // 创建fragment 空的容器 不与页面关联
    const fragment = document.createDocumentFragment()
    // 取出ul中 子节点 保存到fragment
    let child
    // 取出ul的第一个节点赋值给child，如果child为真
    while (child = ul.firstChild) {
      fragment.appendChild(child) // 先将child从ul中移除，然后添加为fragment的子节点
    }
    console.log(fragment.childNodes)
    // 更新fragment中所有li的文本的内容
    Array.prototype.slice.call(fragment.childNodes).forEach(node => {
      // 1 标识元素节点element 
      if (node.nodeType === 1) {
        node.textContent = '哈哈哈'
      }
    })
    ul.appendChild(fragment)
    // 将fragment插入ul
  </script>
</body>
</html>